#!/bin/bash

[ "$EUID" != "0" ] && echo "please run as root" && exit 1
command -v jq >/dev/null 2>&1 || { echo "jq not found"; exit 1; }

if [ $# == 2 ] && [ $2 == "-g" ]; then
	chnroute_enable=0
else
	chnroute_enable=1
fi
udp_proxy=0
#udp proxy is unavailable
verbose=0
reuse_port=1
lower_port_only=1

ss_bin="ss-redir"
ss_rules="./ss-nat"
#ss_rules="ss-nat"
dns_bin="./dns-forwarder_amd64"
ss_json_file="./ss.json"
chnroute_file="./chnroute.txt"

ss_server=$(jq -r .server $ss_json_file)
ss_local_port=$(jq -r .local_port $ss_json_file)

loger() {
	logger -st "$1" "$2"
}

check_chnroute() {
	[ "$chnroute_enable" = "1" ] && [ ! -f $chnroute_file ] && echo "updating chnroute..." && ./update_chnroute.sh
}

check_tproxy() {
	[ "$udp_proxy" = "1" ] && modprobe xt_TPROXY
}

get_arg_udp() {
	[ "$udp_proxy" = "1" ] && echo "-u"
}

get_arg_verbose() {
	[ "$verbose" = "1" ] && echo "-v"
}

get_chnroute() {
	[ "$chnroute_enable" = "1" ] && echo "-i $chnroute_file"
}

get_ipt_ext() {
	[ "$lower_port_only" = "1" ] && echo '-e "--dport 22:1023"'
}

func_run_dns_serv(){
	[ -x "$dns_bin" ] && sh -c "$dns_bin -p 53 &" || { echo "$dns_bin fail!"; return 1; }
	mv -f /etc/resolv.conf /tmp/resolv.conf.backup
	echo "nameserver 127.0.0.1" > /etc/resolv.conf
}

func_stop_dns_serv(){
	[ -f "/tmp/resolv.conf.backup" ] && mv -f /tmp/resolv.conf.backup /etc/resolv.conf
	killall -q "$dns_bin"
}

func_start_ss_redir() {
	threads=0
	while [ $threads -lt $reuse_port ]; do
		$ss_bin -c $ss_json_file "$(get_arg_udp)" "$(get_arg_verbose)" &
		sleep 1 && threads=$((threads+1))
	done
}

func_start_ss_rules() {
	$ss_rules -f
	check_chnroute
	check_tproxy
	sh -c "$ss_rules -o -s $ss_server -l $ss_local_port $(get_chnroute) $(get_ipt_ext) $(get_arg_udp)"
	return $?
}


func_start() {
	func_start_ss_redir && func_start_ss_rules && func_run_dns_serv || { ss-rules -f; echo "ss-script fail!"; }
}

func_stop() {
	killall -q $ss_bin
	$ss_rules -f
	func_stop_dns_serv
}

case "$1" in
start)
	func_start
	;;
stop)
	func_stop
	;;
restart)
	func_stop
	func_start
	;;
*)
	echo "Usage: $0 { start [-g] | stop | restart }"
	exit 1
	;;
esac
